package plugins

import (
	"errors"
	"fmt"
)

type SignatureError struct {
	PluginID        string          `json:"pluginId"`
	SignatureStatus SignatureStatus `json:"status"`
}

var (
	ErrPluginNotInstalled  = errors.New("plugin is not installed")
	ErrUninstallCorePlugin = errors.New("cannot uninstall a Core plugin")
)

type NotFoundError struct {
	PluginID string
}

func (e NotFoundError) Error() string {
	return fmt.Sprintf("plugin with ID '%s' not found", e.PluginID)
}

func (e SignatureError) Error() string {
	switch e.SignatureStatus {
	case SignatureInvalid:
		return fmt.Sprintf("plugin '%s' has an invalid signature", e.PluginID)
	case SignatureModified:
		return fmt.Sprintf("plugin '%s' has an modified signature", e.PluginID)
	case SignatureUnsigned:
		return fmt.Sprintf("plugin '%s' has no signature", e.PluginID)
	case SignatureInternal, SignatureValid:
		return ""
	}

	return fmt.Sprintf("plugin '%s' has an unknown signature state", e.PluginID)
}

type ErrorCode string

type Error struct {
	ErrorCode `json:"errorCode"`
	PluginID  string `json:"pluginId,omitempty"`
}

const (
	signatureMissing  ErrorCode = "signatureMissing"
	signatureModified ErrorCode = "signatureModified"
	signatureInvalid  ErrorCode = "signatureInvalid"
)

func (e SignatureError) AsErrorCode() ErrorCode {
	switch e.SignatureStatus {
	case SignatureInvalid:
		return signatureInvalid
	case SignatureModified:
		return signatureModified
	case SignatureUnsigned:
		return signatureMissing
	case SignatureInternal, SignatureValid:
		return ""
	}

	return ""
}

type SignatureStatus string

func (ss SignatureStatus) IsValid() bool {
	return ss == SignatureValid
}

func (ss SignatureStatus) IsInternal() bool {
	return ss == SignatureInternal
}

const (
	SignatureInternal SignatureStatus = "internal" // core plugin, no signature
	SignatureValid    SignatureStatus = "valid"    // signed and accurate MANIFEST
	SignatureInvalid  SignatureStatus = "invalid"  // invalid signature
	SignatureModified SignatureStatus = "modified" // valid signature, but content mismatch
	SignatureUnsigned SignatureStatus = "unsigned" // no MANIFEST file
)
